#pragma once
#include<iostream>
#include"Socket.hpp"
#include<sys/select.h>



const uint16_t defaultport = 8888;
const int max_fds_num = sizeof(fd_set);
const int defaultfd = -1;


class SelectServer
{
public:
    SelectServer(uint16_t port = defaultport)
    :port_(port) 
    {
        for(int i = 0;i < max_fds_num;i++)
        {
            fd_array[i] = defaultfd;
        }
    }

    void Init()
    {
        listensock_.Socket();
        listensock_.Bind(port_);
        listensock_.Listen();
    }

    void Accept(int listensock)
    {
        std::string client_ip;
        uint16_t client_port;
        int socket = listensock_.Accept(&client_ip,&client_port);
        if(socket < 0) return;
        lg(Info,"accept success,socket is: %d",socket);

        int pos = 0;
        for(;pos < max_fds_num;pos++)
        {
            if(fd_array[pos] != defaultfd) continue;
            else break;
        }

        if(pos == max_fds_num)
        {
            lg(Warning,"Server is full!!!");
            close(socket);
        }
        else
        {
            fd_array[pos] = socket;
            Printfd();
        }
    }

    void Printfd()
    {
        std::cout << "the fd_array has: ";
        for(int i = 0;i < max_fds_num;i++)
        {
            if(fd_array[i] != defaultfd)
            {
                std::cout << fd_array[i] << " ";
            }
        }

        std::cout << std::endl;
    }

    void Dispatcher(fd_set& rfds,int listensock)
    {
        for(int i = 0;i < max_fds_num;i++)
        {
            if(fd_array[i] == defaultfd) continue;

            if(FD_ISSET(fd_array[i],&rfds))
            {
                if(fd_array[i] == listensock)
                {
                    Accept(listensock);
                }
                else
                {
                    Recv(fd_array[i],i);
                }
            }
        }
    }

    void Recv(int fd,int pos)
    {
        char buffer[128];
        int n = read(fd,buffer,sizeof(buffer) -1);
        if(n > 0)
        {
            buffer[n] = 0;
            std::cout << "receive a message: " << buffer << std::endl;
        }
        else if(n == 0)
        {
            lg(Info,"client close the socket,server close too!!!,fd is: %d",fd);
            close(fd);
            fd_array[pos] = defaultfd;
        }
        else
        {
            lg(Warning,"receive message error,fd is: %d",fd);
            close(fd);
            fd_array[pos] = defaultfd;
        }
    }

    void Start()
    {
        int listensock = listensock_.GetSockfd();
        fd_array[0] = listensock;
        int maxfd = listensock;
        for(;;)
        {
            fd_set rfds;
            FD_ZERO(&rfds);

            //将需要等待的文件描述符设置进rfds
            for(int i = 0;i < max_fds_num;i++)
            {
                if(fd_array[i] == defaultfd) continue;

                FD_SET(fd_array[i],&rfds);
                if(maxfd < fd_array[i]) maxfd = fd_array[i];
            }

            struct timeval timeout = {3,0};

            int n = select(maxfd+1,&rfds,nullptr,nullptr,/*&timeout*/nullptr);

            switch(n)
            {
                case -1:
                    lg(Fatal,"select error!!!");
                    break;
                case 0:
                    lg(Info,"time out..........");
                    break;
                default:
                    Dispatcher(rfds,listensock);
                    break;
            }

        }
    }

    ~SelectServer()
    {
        listensock_.Close();
    }
private:
    Sock listensock_;
    u_int16_t port_;
    int fd_array[max_fds_num];
};